﻿namespace ThresholdAssistant.Tools
{
    /// <summary>
    /// JSON格式验证工具类
    /// </summary>
    public static class JsonValidatorUtil
    {
        /// <summary>
        /// 检查字符串是否是JSON格式
        /// </summary>
        /// <param name="jsonValue">JSON字符串</param>
        /// <returns></returns>
        public static bool IsJson(this string jsonValue)
        {
            return IsJson(jsonValue, out int errIndex);
        }

        /// <summary>
        /// 检查字符串是否以JSON字符开头
        /// </summary>
        /// <param name="jsonValue">JSON字符串</param>
        /// <returns></returns>
        public static bool IsJsonStart(this string jsonValue)
        {
            return IsJsonStart(ref jsonValue);
        }

        /// <summary>
        /// 检查字符串是否以JSON字符开头
        /// </summary>
        /// <param name="jsonValue">JSON字符串</param>
        /// <returns></returns>
        private static bool IsJsonStart(ref string jsonValue)
        {
            if (!string.IsNullOrEmpty(jsonValue))
            {
                jsonValue = jsonValue.Trim('\r', '\n', ' ');
                if (jsonValue.Length > 1)
                {
                    char s = jsonValue[0];
                    char e = jsonValue[jsonValue.Length - 1];
                    return (s == '{' && e == '}') || (s == '[' && e == ']');
                }
            }
            return false;
        }

        /// <summary>
        /// 检查字符串是否是JSON格式
        /// </summary>
        /// <param name="jsonValue"></param>
        /// <param name="errIndex"></param>
        /// <returns></returns>
        private static bool IsJson(string jsonValue, out int errIndex)
        {
            errIndex = 0;
            if (IsJsonStart(ref jsonValue))
            {
                char charStr;
                var jsonCharState = new JsonCharState();
                for (int index = 0; index < jsonValue.Length; index++)
                {
                    charStr = jsonValue[index];
                    if (JsonCharState.SetCharState(charStr, ref jsonCharState) && jsonCharState.childrenStart)//设置关键符号状态
                    {
                        var subJsonValue = jsonValue.Substring(index);
                        var length = GetValueLength(subJsonValue, true, out int err);
                        jsonCharState.childrenStart = false;
                        if (err > 0)
                        {
                            errIndex = index + err;
                            return false;
                        }
                        index = index + length - 1;
                    }

                    if (jsonCharState.isError)
                    {
                        errIndex = index;
                        return false;
                    }
                }
                return !jsonCharState.arrayStart && !jsonCharState.jsonStart;
            }
            return false;
        }

        /// <summary>
        /// 获取值的长度（当Json值嵌套以"{"或"["开头时）
        /// </summary>
        /// <param name="jsonValue"></param>
        /// <param name="breakOnErr"></param>
        /// <param name="errIndex"></param>
        /// <returns></returns>
        private static int GetValueLength(string jsonValue, bool breakOnErr, out int errIndex)
        {
            errIndex = 0;
            int len = 0;
            if (!string.IsNullOrEmpty(jsonValue))
            {
                char charStr;
                var jsonCharState = new JsonCharState();
                for (int index = 0; index < jsonValue.Length; index++)
                {
                    charStr = jsonValue[index];
                    if (!JsonCharState.SetCharState(charStr, ref jsonCharState))//设置关键符号状态。
                    {
                        if (!jsonCharState.jsonStart && !jsonCharState.arrayStart)//json结束，又不是数组，则退出
                        {
                            break;
                        }
                    }
                    else if (jsonCharState.childrenStart)//正常字符，值状态下。
                    {
                        var length = GetValueLength(jsonValue.Substring(index), breakOnErr, out errIndex);//递归子值，返回一个长度
                        jsonCharState.childrenStart = false;
                        jsonCharState.valueStart = 0;
                        index = index + length - 1;
                    }
                    if (breakOnErr && jsonCharState.isError)
                    {
                        errIndex = index;
                        return index;
                    }
                    if (!jsonCharState.jsonStart && !jsonCharState.arrayStart)//记录当前结束位置。
                    {
                        len = index + 1;//长度比索引+1
                        break;
                    }
                }
            }
            return len;
        }
    }
}